#ifndef _SURFACE_H_
#define _SURFACE_H_

#include <glm/glm.hpp>
#include <list>
#include "sdl_exception.h"
#include "sdl_event.h"
#include "speaker.h"
#include "shader.h"

// Flag to send to Surface::setVideoMode()
#define USE_DEPTH_BUFFER	0x00001000


namespace sdl {

class Surface;

class SurfaceListener {
public:
	template<int I> struct X { enum { TYPE = I }; };
	typedef X<0> Update;

	virtual void on(Update, Surface*) throw() { }
};


class Surface
	: public Speaker<SurfaceListener>
	, public sdl::EventListener
{
public:
    // Initialize surface
    void setVideoMode(int width, int height, Uint32 flags = 0) throw (sdl::Exception);

	// Plot a pixel on the surface
	void putPixel(int x, int y, const glm::vec3& color);
    // Retrieve color from the position
    void getpixel(int x, int y, glm::vec3* color);
	// Fill rectangle. If rc is NULL method will fill the whole area.
	void fill(SDL_Rect* rc, Uint32 color);
	// Draw line
	void drawLine(int x0, int y0, int x1, int y1, const glm::vec3& color);
	void drawLine(const glm::vec3& begin, const glm::vec3& end, const Shader& col);

	void drawHorLine(int x1, int x2, int y, const glm::vec3& col);

	// Take a screenshot to a file
	void saveBmp(const char* fname);
	// Redraw surface
	void update();

	// Get width of current surface
	int getWidth() const {
		return _surface->w;
	}
	// Get height of current surface
	int getHeight() const {
		return _surface->h;
	}

protected:
    Surface();
	virtual ~Surface() throw();

	void on(EventListener::NewEvent, const SDL_Event*) throw();
	void freeDepthBuffer();

	// sdl pointer
	SDL_Surface* _surface;
	// Depth buffer (if enabled)
	float** _depthBuffer;
};

} // namespace sdl

#endif // _SURFACE_H_

